import CryptoJS from 'crypto-js'

// DES加密结果
export interface DESResult {
  encrypted: string
  iv?: string
}

/**
 * 3DES加密
 * @param plaintext 明文
 * @param key 密钥（hex格式）
 * @param iv 初始向量（可选）
 */
export const DESEncrypt = (
  plaintext: string,
  key: string,
  iv?: string
): DESResult => {
  try {
    // 3DES需要24字节密钥，如果不足则重复填充
    let desKey = key
    while (desKey.length < 48) { // 24字节 = 48个hex字符
      desKey += key
    }
    desKey = desKey.substring(0, 48)

    const keyWords = CryptoJS.enc.Hex.parse(desKey)
    const ivWords = iv ? CryptoJS.enc.Hex.parse(iv) : CryptoJS.lib.WordArray.random(8)

    const encrypted = CryptoJS.TripleDES.encrypt(plaintext, keyWords, {
      iv: ivWords,
      mode: CryptoJS.mode.CBC,
      padding: CryptoJS.pad.Pkcs7
    })

    return {
      encrypted: encrypted.ciphertext.toString(CryptoJS.enc.Base64),
      iv: ivWords.toString(CryptoJS.enc.Hex)
    }

  } catch (error) {
    throw new Error(`3DES加密失败: ${error}`)
  }
}

/**
 * 3DES解密
 * @param encryptedData 加密数据（base64格式）
 * @param key 密钥（hex格式）
 * @param iv 初始向量（hex格式）
 */
export const DESDecrypt = (
  encryptedData: string,
  key: string,
  iv?: string
): string => {
  try {
    if (!iv) {
      throw new Error('缺少初始向量')
    }

    // 3DES需要24字节密钥
    let desKey = key
    while (desKey.length < 48) {
      desKey += key
    }
    desKey = desKey.substring(0, 48)

    const keyWords = CryptoJS.enc.Hex.parse(desKey)
    const ivWords = CryptoJS.enc.Hex.parse(iv)
    const encryptedWords = CryptoJS.enc.Base64.parse(encryptedData)

    const cipherParams = CryptoJS.lib.CipherParams.create({
      ciphertext: encryptedWords
    })

    const decrypted = CryptoJS.TripleDES.decrypt(cipherParams, keyWords, {
      iv: ivWords,
      mode: CryptoJS.mode.CBC,
      padding: CryptoJS.pad.Pkcs7
    })

    const result = decrypted.toString(CryptoJS.enc.Utf8)

    if (!result) {
      throw new Error('解密失败，可能密钥错误')
    }

    return result

  } catch (error) {
    throw new Error(`3DES解密失败: ${error}`)
  }
}

/**
 * 生成3DES密钥
 */
export const generate3DESKey = (): string => {
  return CryptoJS.lib.WordArray.random(24).toString(CryptoJS.enc.Hex)
}